/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
var mxEvent =
    {

        /**
         * Class: mxEvent
         *
         * Cross-browser DOM event support. For internal event handling,
         * <mxEventSource> and the graph event dispatch loop in <mxGraph> are used.
         *
         * Memory Leaks:
         *
         * Use this class for adding and removing listeners to/from DOM nodes. The
         * <removeAllListeners> function is provided to remove all listeners that
         * have been added using <addListener>. The function should be invoked when
         * the last reference is removed in the JavaScript code, typically when the
         * referenced DOM node is removed from the DOM.
         *
         * Function: addListener
         *
         * Binds the function to the specified event on the given element. Use
         * <mxUtils.bind> in order to bind the "this" keyword inside the function
         * to a given execution scope.
         */
        addListener: function()
        {
            var updateListenerList = function(element, eventName, funct)
            {
                if (element.mxListenerList == null)
                {
                    element.mxListenerList = [];
                }

                var entry = {name: eventName, f: funct};
                element.mxListenerList.push(entry);
            };

            if (window.addEventListener)
            {
                return function(element, eventName, funct)
                {
                    element.addEventListener(eventName, funct, false);
                    updateListenerList(element, eventName, funct);
                };
            }
            else
            {
                return function(element, eventName, funct)
                {
                    element.attachEvent('on' + eventName, funct);
                    updateListenerList(element, eventName, funct);
                };
            }
        }(),

        /**
         * Function: removeListener
         *
         * Removes the specified listener from the given element.
         */
        removeListener: function()
        {
            var updateListener = function(element, eventName, funct)
            {
                if (element.mxListenerList != null)
                {
                    var listenerCount = element.mxListenerList.length;

                    for (var i = 0; i < listenerCount; i++)
                    {
                        var entry = element.mxListenerList[i];

                        if (entry.f == funct)
                        {
                            element.mxListenerList.splice(i, 1);
                            break;
                        }
                    }

                    if (element.mxListenerList.length == 0)
                    {
                        element.mxListenerList = null;
                    }
                }
            };

            if (window.removeEventListener)
            {
                return function(element, eventName, funct)
                {
                    element.removeEventListener(eventName, funct, false);
                    updateListener(element, eventName, funct);
                };
            }
            else
            {
                return function(element, eventName, funct)
                {
                    element.detachEvent('on' + eventName, funct);
                    updateListener(element, eventName, funct);
                };
            }
        }(),

        /**
         * Function: removeAllListeners
         *
         * Removes all listeners from the given element.
         */
        removeAllListeners: function(element)
        {
            var list = element.mxListenerList;

            if (list != null)
            {
                while (list.length > 0)
                {
                    var entry = list[0];
                    mxEvent.removeListener(element, entry.name, entry.f);
                }
            }
        },

        /**
         * Function: addGestureListeners
         *
         * Adds the given listeners for touch, mouse and/or pointer events. If
         * <mxClient.IS_POINTER> is true then pointer events will be registered,
         * else the respective mouse events will be registered. If <mxClient.IS_POINTER>
         * is false and <mxClient.IS_TOUCH> is true then the respective touch events
         * will be registered as well as the mouse events.
         */
        addGestureListeners: function(node, startListener, moveListener, endListener)
        {
            if (startListener != null)
            {
                mxEvent.addListener(node, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', startListener);
            }

            if (moveListener != null)
            {
                mxEvent.addListener(node, (mxClient.IS_POINTER) ? 'pointermove' : 'mousemove', moveListener);
            }

            if (endListener != null)
            {
                mxEvent.addListener(node, (mxClient.IS_POINTER) ? 'pointerup' : 'mouseup', endListener);
            }

            if (!mxClient.IS_POINTER && mxClient.IS_TOUCH)
            {
                if (startListener != null)
                {
                    mxEvent.addListener(node, 'touchstart', startListener);
                }

                if (moveListener != null)
                {
                    mxEvent.addListener(node, 'touchmove', moveListener);
                }

                if (endListener != null)
                {
                    mxEvent.addListener(node, 'touchend', endListener);
                }
            }
        },

        /**
         * Function: removeGestureListeners
         *
         * Removes the given listeners from mousedown, mousemove, mouseup and the
         * respective touch events if <mxClient.IS_TOUCH> is true.
         */
        removeGestureListeners: function(node, startListener, moveListener, endListener)
        {
            if (startListener != null)
            {
                mxEvent.removeListener(node, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown', startListener);
            }

            if (moveListener != null)
            {
                mxEvent.removeListener(node, (mxClient.IS_POINTER) ? 'pointermove' : 'mousemove', moveListener);
            }

            if (endListener != null)
            {
                mxEvent.removeListener(node, (mxClient.IS_POINTER) ? 'pointerup' : 'mouseup', endListener);
            }

            if (!mxClient.IS_POINTER && mxClient.IS_TOUCH)
            {
                if (startListener != null)
                {
                    mxEvent.removeListener(node, 'touchstart', startListener);
                }

                if (moveListener != null)
                {
                    mxEvent.removeListener(node, 'touchmove', moveListener);
                }

                if (endListener != null)
                {
                    mxEvent.removeListener(node, 'touchend', endListener);
                }
            }
        },

        /**
         * Function: redirectMouseEvents
         *
         * Redirects the mouse events from the given DOM node to the graph dispatch
         * loop using the event and given state as event arguments. State can
         * either be an instance of <mxCellState> or a function that returns an
         * <mxCellState>. The down, move, up and dblClick arguments are optional
         * functions that take the trigger event as arguments and replace the
         * default behaviour.
         */
        redirectMouseEvents: function(node, graph, state, down, move, up, dblClick)
        {
            var getState = function(evt)
            {
                return (typeof(state) == 'function') ? state(evt) : state;
            };

            mxEvent.addGestureListeners(node, function (evt)
                {
                    if (down != null)
                    {
                        down(evt);
                    }
                    else if (!mxEvent.isConsumed(evt))
                    {
                        graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt, getState(evt)));
                    }
                },
                function (evt)
                {
                    if (move != null)
                    {
                        move(evt);
                    }
                    else if (!mxEvent.isConsumed(evt))
                    {
                        graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt, getState(evt)));
                    }
                },
                function (evt)
                {
                    if (up != null)
                    {
                        up(evt);
                    }
                    else if (!mxEvent.isConsumed(evt))
                    {
                        graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt, getState(evt)));
                    }
                });

            mxEvent.addListener(node, 'dblclick', function (evt)
            {
                if (dblClick != null)
                {
                    dblClick(evt);
                }
                else if (!mxEvent.isConsumed(evt))
                {
                    var tmp = getState(evt);
                    graph.dblClick(evt, (tmp != null) ? tmp.cell : null);
                }
            });
        },

        /**
         * Function: release
         *
         * Removes the known listeners from the given DOM node and its descendants.
         *
         * Parameters:
         *
         * element - DOM node to remove the listeners from.
         */
        release: function(element)
        {
            try
            {
                if (element != null)
                {
                    mxEvent.removeAllListeners(element);

                    var children = element.childNodes;

                    if (children != null)
                    {
                        var childCount = children.length;

                        for (var i = 0; i < childCount; i += 1)
                        {
                            mxEvent.release(children[i]);
                        }
                    }
                }
            }
            catch (e)
            {
                // ignores errors as this is typically called in cleanup code
            }
        },

        /**
         * Function: addMouseWheelListener
         *
         * Installs the given function as a handler for mouse wheel events. The
         * function has two arguments: the mouse event and a boolean that specifies
         * if the wheel was moved up or down.
         *
         * This has been tested with IE 6 and 7, Firefox (all versions), Opera and
         * Safari. It does currently not work on Safari for Mac.
         *
         * Example:
         *
         * (code)
         * mxEvent.addMouseWheelListener(function (evt, up)
         * {
         *   mxLog.show();
         *   mxLog.debug('mouseWheel: up='+up);
         * });
         *(end)
         *
         * Parameters:
         *
         * funct - Handler function that takes the event argument and a boolean up
         * argument for the mousewheel direction.
         * target - Target for installing the listener in Google Chrome. See
         * https://www.chromestatus.com/features/6662647093133312.
         */
        addMouseWheelListener: function(funct, target)
        {
            if (funct != null)
            {
                var wheelHandler = function(evt)
                {
                    // IE does not give an event object but the
                    // global event object is the mousewheel event
                    // at this point in time.
                    if (evt == null)
                    {
                        evt = window.event;
                    }

                    var delta = 0;

                    if (mxClient.IS_FF)
                    {
                        delta = -evt.detail / 2;
                    }
                    else
                    {
                        delta = evt.wheelDelta / 120;
                    }

                    // Handles the event using the given function
                    if (delta != 0)
                    {
                        funct(evt, delta > 0);
                    }
                };

                // Webkit has NS event API, but IE event name and details
                if (mxClient.IS_NS && document.documentMode == null)
                {
                    var eventName = (mxClient.IS_SF || mxClient.IS_GC) ? 'mousewheel' : 'DOMMouseScroll';
                    mxEvent.addListener((mxClient.IS_GC && target != null) ? target : window,
                        eventName, wheelHandler);
                }
                else
                {
                    mxEvent.addListener(document, 'mousewheel', wheelHandler);
                }
            }
        },

        /**
         * Function: disableContextMenu
         *
         * Disables the context menu for the given element.
         */
        disableContextMenu: function(element)
        {
            mxEvent.addListener(element, 'contextmenu', function(evt)
            {
                if (evt.preventDefault)
                {
                    evt.preventDefault();
                }

                return false;
            });
        },

        /**
         * Function: getSource
         *
         * Returns the event's target or srcElement depending on the browser.
         */
        getSource: function(evt)
        {
            return (evt.srcElement != null) ? evt.srcElement : evt.target;
        },

        /**
         * Function: isConsumed
         *
         * Returns true if the event has been consumed using <consume>.
         */
        isConsumed: function(evt)
        {
            return evt.isConsumed != null && evt.isConsumed;
        },

        /**
         * Function: isTouchEvent
         *
         * Returns true if the event was generated using a touch device (not a pen or mouse).
         */
        isTouchEvent: function(evt)
        {
            return (evt.pointerType != null) ? (evt.pointerType == 'touch' || evt.pointerType ===
                evt.MSPOINTER_TYPE_TOUCH) : ((evt.mozInputSource != null) ?
                evt.mozInputSource == 5 : evt.type.indexOf('touch') == 0);
        },

        /**
         * Function: isPenEvent
         *
         * Returns true if the event was generated using a pen (not a touch device or mouse).
         */
        isPenEvent: function(evt)
        {
            return (evt.pointerType != null) ? (evt.pointerType == 'pen' || evt.pointerType ===
                evt.MSPOINTER_TYPE_PEN) : ((evt.mozInputSource != null) ?
                evt.mozInputSource == 2 : evt.type.indexOf('pen') == 0);
        },

        /**
         * Function: isMultiTouchEvent
         *
         * Returns true if the event was generated using a touch device (not a pen or mouse).
         */
        isMultiTouchEvent: function(evt)
        {
            return (evt.type != null && evt.type.indexOf('touch') == 0 && evt.touches != null && evt.touches.length > 1);
        },

        /**
         * Function: isMouseEvent
         *
         * Returns true if the event was generated using a mouse (not a pen or touch device).
         */
        isMouseEvent: function(evt)
        {
            return (evt.pointerType != null) ? (evt.pointerType == 'mouse' || evt.pointerType ===
                evt.MSPOINTER_TYPE_MOUSE) : ((evt.mozInputSource != null) ?
                evt.mozInputSource == 1 : evt.type.indexOf('mouse') == 0);
        },

        /**
         * Function: isLeftMouseButton
         *
         * Returns true if the left mouse button is pressed for the given event.
         * To check if a button is pressed during a mouseMove you should use the
         * <mxGraph.isMouseDown> property. Note that this returns true in Firefox
         * for control+left-click on the Mac.
         */
        isLeftMouseButton: function(evt)
        {
            // Special case for mousemove and mousedown we check the buttons
            // if it exists because which is 0 even if no button is pressed
            if ('buttons' in evt && (evt.type == 'mousedown' || evt.type == 'mousemove'))
            {
                return evt.buttons == 1;
            }
            else if ('which' in evt)
            {
                return evt.which === 1;
            }
            else
            {
                return evt.button === 1;
            }
        },

        /**
         * Function: isMiddleMouseButton
         *
         * Returns true if the middle mouse button is pressed for the given event.
         * To check if a button is pressed during a mouseMove you should use the
         * <mxGraph.isMouseDown> property.
         */
        isMiddleMouseButton: function(evt)
        {
            if ('which' in evt)
            {
                return evt.which === 2;
            }
            else
            {
                return evt.button === 4;
            }
        },

        /**
         * Function: isRightMouseButton
         *
         * Returns true if the right mouse button was pressed. Note that this
         * button might not be available on some systems. For handling a popup
         * trigger <isPopupTrigger> should be used.
         */
        isRightMouseButton: function(evt)
        {
            if ('which' in evt)
            {
                return evt.which === 3;
            }
            else
            {
                return evt.button === 2;
            }
        },

        /**
         * Function: isPopupTrigger
         *
         * Returns true if the event is a popup trigger. This implementation
         * returns true if the right button or the left button and control was
         * pressed on a Mac.
         */
        isPopupTrigger: function(evt)
        {
            return mxEvent.isRightMouseButton(evt) || (mxClient.IS_MAC && mxEvent.isControlDown(evt) &&
                !mxEvent.isShiftDown(evt) && !mxEvent.isMetaDown(evt) && !mxEvent.isAltDown(evt));
        },

        /**
         * Function: isShiftDown
         *
         * Returns true if the shift key is pressed for the given event.
         */
        isShiftDown: function(evt)
        {
            return (evt != null) ? evt.shiftKey : false;
        },

        /**
         * Function: isAltDown
         *
         * Returns true if the alt key is pressed for the given event.
         */
        isAltDown: function(evt)
        {
            return (evt != null) ? evt.altKey : false;
        },

        /**
         * Function: isControlDown
         *
         * Returns true if the control key is pressed for the given event.
         */
        isControlDown: function(evt)
        {
            return (evt != null) ? evt.ctrlKey : false;
        },

        /**
         * Function: isMetaDown
         *
         * Returns true if the meta key is pressed for the given event.
         */
        isMetaDown: function(evt)
        {
            return (evt != null) ? evt.metaKey : false;
        },

        /**
         * Function: getMainEvent
         *
         * Returns the touch or mouse event that contains the mouse coordinates.
         */
        getMainEvent: function(e)
        {
            if ((e.type == 'touchstart' || e.type == 'touchmove') && e.touches != null && e.touches[0] != null)
            {
                e = e.touches[0];
            }
            else if (e.type == 'touchend' && e.changedTouches != null && e.changedTouches[0] != null)
            {
                e = e.changedTouches[0];
            }

            return e;
        },

        /**
         * Function: getClientX
         *
         * Returns true if the meta key is pressed for the given event.
         */
        getClientX: function(e)
        {
            return mxEvent.getMainEvent(e).clientX;
        },

        /**
         * Function: getClientY
         *
         * Returns true if the meta key is pressed for the given event.
         */
        getClientY: function(e)
        {
            return mxEvent.getMainEvent(e).clientY;
        },

        /**
         * Function: consume
         *
         * Consumes the given event.
         *
         * Parameters:
         *
         * evt - Native event to be consumed.
         * preventDefault - Optional boolean to prevent the default for the event.
         * Default is true.
         * stopPropagation - Option boolean to stop event propagation. Default is
         * true.
         */
        consume: function(evt, preventDefault, stopPropagation)
        {
            preventDefault = (preventDefault != null) ? preventDefault : true;
            stopPropagation = (stopPropagation != null) ? stopPropagation : true;

            if (preventDefault)
            {
                if (evt.preventDefault)
                {
                    if (stopPropagation)
                    {
                        evt.stopPropagation();
                    }

                    evt.preventDefault();
                }
                else if (stopPropagation)
                {
                    evt.cancelBubble = true;
                }
            }

            // Opera
            evt.isConsumed = true;

            // Other browsers
            if (!evt.preventDefault)
            {
                evt.returnValue = false;
            }
        },

        //
        // Special handles in mouse events
        //

        /**
         * Variable: LABEL_HANDLE
         *
         * Index for the label handle in an mxMouseEvent. This should be a negative
         * value that does not interfere with any possible handle indices. Default
         * is -1.
         */
        LABEL_HANDLE: -1,

        /**
         * Variable: ROTATION_HANDLE
         *
         * Index for the rotation handle in an mxMouseEvent. This should be a
         * negative value that does not interfere with any possible handle indices.
         * Default is -2.
         */
        ROTATION_HANDLE: -2,

        /**
         * Variable: CUSTOM_HANDLE
         *
         * Start index for the custom handles in an mxMouseEvent. This should be a
         * negative value and is the start index which is decremented for each
         * custom handle. Default is -100.
         */
        CUSTOM_HANDLE: -100,

        /**
         * Variable: VIRTUAL_HANDLE
         *
         * Start index for the virtual handles in an mxMouseEvent. This should be a
         * negative value and is the start index which is decremented for each
         * virtual handle. Default is -100000. This assumes that there are no more
         * than VIRTUAL_HANDLE - CUSTOM_HANDLE custom handles.
         *
         */
        VIRTUAL_HANDLE: -100000,

        //
        // Event names
        //

        /**
         * Variable: MOUSE_DOWN
         *
         * Specifies the event name for mouseDown.
         */
        MOUSE_DOWN: 'mouseDown',

        /**
         * Variable: MOUSE_MOVE
         *
         * Specifies the event name for mouseMove.
         */
        MOUSE_MOVE: 'mouseMove',

        /**
         * Variable: MOUSE_UP
         *
         * Specifies the event name for mouseUp.
         */
        MOUSE_UP: 'mouseUp',

        /**
         * Variable: ACTIVATE
         *
         * Specifies the event name for activate.
         */
        ACTIVATE: 'activate',

        /**
         * Variable: RESIZE_START
         *
         * Specifies the event name for resizeStart.
         */
        RESIZE_START: 'resizeStart',

        /**
         * Variable: RESIZE
         *
         * Specifies the event name for resize.
         */
        RESIZE: 'resize',

        /**
         * Variable: RESIZE_END
         *
         * Specifies the event name for resizeEnd.
         */
        RESIZE_END: 'resizeEnd',

        /**
         * Variable: MOVE_START
         *
         * Specifies the event name for moveStart.
         */
        MOVE_START: 'moveStart',

        /**
         * Variable: MOVE
         *
         * Specifies the event name for move.
         */
        MOVE: 'move',

        /**
         * Variable: MOVE_END
         *
         * Specifies the event name for moveEnd.
         */
        MOVE_END: 'moveEnd',

        /**
         * Variable: PAN_START
         *
         * Specifies the event name for panStart.
         */
        PAN_START: 'panStart',

        /**
         * Variable: PAN
         *
         * Specifies the event name for pan.
         */
        PAN: 'pan',

        /**
         * Variable: PAN_END
         *
         * Specifies the event name for panEnd.
         */
        PAN_END: 'panEnd',

        /**
         * Variable: MINIMIZE
         *
         * Specifies the event name for minimize.
         */
        MINIMIZE: 'minimize',

        /**
         * Variable: NORMALIZE
         *
         * Specifies the event name for normalize.
         */
        NORMALIZE: 'normalize',

        /**
         * Variable: MAXIMIZE
         *
         * Specifies the event name for maximize.
         */
        MAXIMIZE: 'maximize',

        /**
         * Variable: HIDE
         *
         * Specifies the event name for hide.
         */
        HIDE: 'hide',

        /**
         * Variable: SHOW
         *
         * Specifies the event name for show.
         */
        SHOW: 'show',

        /**
         * Variable: CLOSE
         *
         * Specifies the event name for close.
         */
        CLOSE: 'close',

        /**
         * Variable: DESTROY
         *
         * Specifies the event name for destroy.
         */
        DESTROY: 'destroy',

        /**
         * Variable: REFRESH
         *
         * Specifies the event name for refresh.
         */
        REFRESH: 'refresh',

        /**
         * Variable: SIZE
         *
         * Specifies the event name for size.
         */
        SIZE: 'size',

        /**
         * Variable: SELECT
         *
         * Specifies the event name for select.
         */
        SELECT: 'select',

        /**
         * Variable: FIRED
         *
         * Specifies the event name for fired.
         */
        FIRED: 'fired',

        /**
         * Variable: FIRE_MOUSE_EVENT
         *
         * Specifies the event name for fireMouseEvent.
         */
        FIRE_MOUSE_EVENT: 'fireMouseEvent',

        /**
         * Variable: GESTURE
         *
         * Specifies the event name for gesture.
         */
        GESTURE: 'gesture',

        /**
         * Variable: TAP_AND_HOLD
         *
         * Specifies the event name for tapAndHold.
         */
        TAP_AND_HOLD: 'tapAndHold',

        /**
         * Variable: GET
         *
         * Specifies the event name for get.
         */
        GET: 'get',

        /**
         * Variable: RECEIVE
         *
         * Specifies the event name for receive.
         */
        RECEIVE: 'receive',

        /**
         * Variable: CONNECT
         *
         * Specifies the event name for connect.
         */
        CONNECT: 'connect',

        /**
         * Variable: DISCONNECT
         *
         * Specifies the event name for disconnect.
         */
        DISCONNECT: 'disconnect',

        /**
         * Variable: SUSPEND
         *
         * Specifies the event name for suspend.
         */
        SUSPEND: 'suspend',

        /**
         * Variable: RESUME
         *
         * Specifies the event name for suspend.
         */
        RESUME: 'resume',

        /**
         * Variable: MARK
         *
         * Specifies the event name for mark.
         */
        MARK: 'mark',

        /**
         * Variable: ROOT
         *
         * Specifies the event name for root.
         */
        ROOT: 'root',

        /**
         * Variable: POST
         *
         * Specifies the event name for post.
         */
        POST: 'post',

        /**
         * Variable: OPEN
         *
         * Specifies the event name for open.
         */
        OPEN: 'open',

        /**
         * Variable: SAVE
         *
         * Specifies the event name for open.
         */
        SAVE: 'save',

        /**
         * Variable: BEFORE_ADD_VERTEX
         *
         * Specifies the event name for beforeAddVertex.
         */
        BEFORE_ADD_VERTEX: 'beforeAddVertex',

        /**
         * Variable: ADD_VERTEX
         *
         * Specifies the event name for addVertex.
         */
        ADD_VERTEX: 'addVertex',

        /**
         * Variable: AFTER_ADD_VERTEX
         *
         * Specifies the event name for afterAddVertex.
         */
        AFTER_ADD_VERTEX: 'afterAddVertex',

        /**
         * Variable: DONE
         *
         * Specifies the event name for done.
         */
        DONE: 'done',

        /**
         * Variable: EXECUTE
         *
         * Specifies the event name for execute.
         */
        EXECUTE: 'execute',

        /**
         * Variable: EXECUTED
         *
         * Specifies the event name for executed.
         */
        EXECUTED: 'executed',

        /**
         * Variable: BEGIN_UPDATE
         *
         * Specifies the event name for beginUpdate.
         */
        BEGIN_UPDATE: 'beginUpdate',

        /**
         * Variable: START_EDIT
         *
         * Specifies the event name for startEdit.
         */
        START_EDIT: 'startEdit',

        /**
         * Variable: END_UPDATE
         *
         * Specifies the event name for endUpdate.
         */
        END_UPDATE: 'endUpdate',

        /**
         * Variable: END_EDIT
         *
         * Specifies the event name for endEdit.
         */
        END_EDIT: 'endEdit',

        /**
         * Variable: BEFORE_UNDO
         *
         * Specifies the event name for beforeUndo.
         */
        BEFORE_UNDO: 'beforeUndo',

        /**
         * Variable: UNDO
         *
         * Specifies the event name for undo.
         */
        UNDO: 'undo',

        /**
         * Variable: REDO
         *
         * Specifies the event name for redo.
         */
        REDO: 'redo',

        /**
         * Variable: CHANGE
         *
         * Specifies the event name for change.
         */
        CHANGE: 'change',

        /**
         * Variable: NOTIFY
         *
         * Specifies the event name for notify.
         */
        NOTIFY: 'notify',

        /**
         * Variable: LAYOUT_CELLS
         *
         * Specifies the event name for layoutCells.
         */
        LAYOUT_CELLS: 'layoutCells',

        /**
         * Variable: CLICK
         *
         * Specifies the event name for click.
         */
        CLICK: 'click',

        /**
         * Variable: SCALE
         *
         * Specifies the event name for scale.
         */
        SCALE: 'scale',

        /**
         * Variable: TRANSLATE
         *
         * Specifies the event name for translate.
         */
        TRANSLATE: 'translate',

        /**
         * Variable: SCALE_AND_TRANSLATE
         *
         * Specifies the event name for scaleAndTranslate.
         */
        SCALE_AND_TRANSLATE: 'scaleAndTranslate',

        /**
         * Variable: UP
         *
         * Specifies the event name for up.
         */
        UP: 'up',

        /**
         * Variable: DOWN
         *
         * Specifies the event name for down.
         */
        DOWN: 'down',

        /**
         * Variable: ADD
         *
         * Specifies the event name for add.
         */
        ADD: 'add',

        /**
         * Variable: REMOVE
         *
         * Specifies the event name for remove.
         */
        REMOVE: 'remove',

        /**
         * Variable: CLEAR
         *
         * Specifies the event name for clear.
         */
        CLEAR: 'clear',

        /**
         * Variable: ADD_CELLS
         *
         * Specifies the event name for addCells.
         */
        ADD_CELLS: 'addCells',

        /**
         * Variable: CELLS_ADDED
         *
         * Specifies the event name for cellsAdded.
         */
        CELLS_ADDED: 'cellsAdded',

        /**
         * Variable: MOVE_CELLS
         *
         * Specifies the event name for moveCells.
         */
        MOVE_CELLS: 'moveCells',

        /**
         * Variable: CELLS_MOVED
         *
         * Specifies the event name for cellsMoved.
         */
        CELLS_MOVED: 'cellsMoved',

        /**
         * Variable: RESIZE_CELLS
         *
         * Specifies the event name for resizeCells.
         */
        RESIZE_CELLS: 'resizeCells',

        /**
         * Variable: CELLS_RESIZED
         *
         * Specifies the event name for cellsResized.
         */
        CELLS_RESIZED: 'cellsResized',

        /**
         * Variable: TOGGLE_CELLS
         *
         * Specifies the event name for toggleCells.
         */
        TOGGLE_CELLS: 'toggleCells',

        /**
         * Variable: CELLS_TOGGLED
         *
         * Specifies the event name for cellsToggled.
         */
        CELLS_TOGGLED: 'cellsToggled',

        /**
         * Variable: ORDER_CELLS
         *
         * Specifies the event name for orderCells.
         */
        ORDER_CELLS: 'orderCells',

        /**
         * Variable: CELLS_ORDERED
         *
         * Specifies the event name for cellsOrdered.
         */
        CELLS_ORDERED: 'cellsOrdered',

        /**
         * Variable: REMOVE_CELLS
         *
         * Specifies the event name for removeCells.
         */
        REMOVE_CELLS: 'removeCells',

        /**
         * Variable: CELLS_REMOVED
         *
         * Specifies the event name for cellsRemoved.
         */
        CELLS_REMOVED: 'cellsRemoved',

        /**
         * Variable: GROUP_CELLS
         *
         * Specifies the event name for groupCells.
         */
        GROUP_CELLS: 'groupCells',

        /**
         * Variable: UNGROUP_CELLS
         *
         * Specifies the event name for ungroupCells.
         */
        UNGROUP_CELLS: 'ungroupCells',

        /**
         * Variable: REMOVE_CELLS_FROM_PARENT
         *
         * Specifies the event name for removeCellsFromParent.
         */
        REMOVE_CELLS_FROM_PARENT: 'removeCellsFromParent',

        /**
         * Variable: FOLD_CELLS
         *
         * Specifies the event name for foldCells.
         */
        FOLD_CELLS: 'foldCells',

        /**
         * Variable: CELLS_FOLDED
         *
         * Specifies the event name for cellsFolded.
         */
        CELLS_FOLDED: 'cellsFolded',

        /**
         * Variable: ALIGN_CELLS
         *
         * Specifies the event name for alignCells.
         */
        ALIGN_CELLS: 'alignCells',

        /**
         * Variable: LABEL_CHANGED
         *
         * Specifies the event name for labelChanged.
         */
        LABEL_CHANGED: 'labelChanged',

        /**
         * Variable: CONNECT_CELL
         *
         * Specifies the event name for connectCell.
         */
        CONNECT_CELL: 'connectCell',

        /**
         * Variable: CELL_CONNECTED
         *
         * Specifies the event name for cellConnected.
         */
        CELL_CONNECTED: 'cellConnected',

        /**
         * Variable: SPLIT_EDGE
         *
         * Specifies the event name for splitEdge.
         */
        SPLIT_EDGE: 'splitEdge',

        /**
         * Variable: FLIP_EDGE
         *
         * Specifies the event name for flipEdge.
         */
        FLIP_EDGE: 'flipEdge',

        /**
         * Variable: START_EDITING
         *
         * Specifies the event name for startEditing.
         */
        START_EDITING: 'startEditing',

        /**
         * Variable: EDITING_STARTED
         *
         * Specifies the event name for editingStarted.
         */
        EDITING_STARTED: 'editingStarted',

        /**
         * Variable: EDITING_STOPPED
         *
         * Specifies the event name for editingStopped.
         */
        EDITING_STOPPED: 'editingStopped',

        /**
         * Variable: ADD_OVERLAY
         *
         * Specifies the event name for addOverlay.
         */
        ADD_OVERLAY: 'addOverlay',

        /**
         * Variable: REMOVE_OVERLAY
         *
         * Specifies the event name for removeOverlay.
         */
        REMOVE_OVERLAY: 'removeOverlay',

        /**
         * Variable: UPDATE_CELL_SIZE
         *
         * Specifies the event name for updateCellSize.
         */
        UPDATE_CELL_SIZE: 'updateCellSize',

        /**
         * Variable: ESCAPE
         *
         * Specifies the event name for escape.
         */
        ESCAPE: 'escape',

        /**
         * Variable: DOUBLE_CLICK
         *
         * Specifies the event name for doubleClick.
         */
        DOUBLE_CLICK: 'doubleClick',

        /**
         * Variable: START
         *
         * Specifies the event name for start.
         */
        START: 'start',

        /**
         * Variable: RESET
         *
         * Specifies the event name for reset.
         */
        RESET: 'reset'

    };
